      *=====================================================================*
      *  Job Log API                                                        *
      *=====================================================================*
      *  Author  :  Thomas Raddatz                                          *
      *  Date    :  19.05.2013                                              *
      *  E-mail  :  thomas.raddatz@Tools400.de                              *
      *  Homepage:  www.tools400.de                                         *
      *=====================================================================*
      *                                                                     *
      *  This software is free software, you can redistribute it and/or     *
      *  modify it under the terms of the GNU General Public License (GPL)  *
      *  as published by the Free Software Foundation.                      *
      *                                                                     *
      *  See GNU General Public License for details.                        *
      *          http://www.opensource.org                                  *
      *          http://www.opensource.org/licenses/gpl-license.html        *
      *                                                                     *
      *=====================================================================*
      *  History:                                                           *
      *                                                                     *
      *  Date        Name          Description                              *
      *  ----------  ------------  ---------------------------------------  *
      *                                                                     *
      *=====================================================================*
      *   >>PRE-COMPILER<<                                                  *
      *     >>CRTCMD<<  CRTRPGMOD   MODULE(&LI/&OB) +                       *
      *                             SRCFILE(&SL/&SF) +                      *
      *                             SRCMBR(&SM);                            *
      *     >>COMPILE<<                                                     *
      *       >>PARM<< TRUNCNBR(*NO);                                       *
      *       >>PARM<< DBGVIEW(*LIST);                                      *
      *       >>PARM<< OPTION(*EVENTF);                                     *
      *     >>END-COMPILE<<                                                 *
      *     >>EXECUTE<<                                                     *
      *   >>END-PRE-COMPILER<<                                              *
      *=====================================================================*
 CPY H NOMAIN BNDDIR('QC2LE')
      /COPY QJOBLOG,H_SPEC
      /COPY QJOBLOG,COPYRIGHT
      *=====================================================================*
      *
      * ------------------------------------
      *  Constants
      * ------------------------------------
     D MSGKEY_NEXT...
     D                 c                   x'00000000'
     D MSGKEY_PREVIOUS...
     D                 c                   x'FFFFFFFF'
      *
      * ------------------------------------
      *  Type Definitions
      * ------------------------------------
     D handle_t        ds                  qualified based(pDummy)
     D  isOpen                         n
     D  isEOF                          n
     D  qJob                               likeds(qJob_t)
     D  direction                          like(JobLog_direction_t)
     D  strMsgKey                          like(JobLog_msgKey_t)
     D  rcdNbr                       10i 0
     D  listInf                            likeds(qgy_opnListInf_t)
     D  options                            likeds(listOptions_t)
      *
     D listOptions_t   ds                  qualified based(pDummy)
     D  isMsg                          n
     D  msgSelectId                  10i 0
     D  isMsgHelp                      n
     D  hlpSelectId                  10i 0
     D  isSender                       n
     D  isReceiver                     n
      *
     D mixedData_t     ds                  likeds(JobLog_stmts_t)
      *
      * ------------------------------------
      *  Exported prototypes
      * ------------------------------------
      /COPY QJOBLOG,PJOBLOG
      *
      * ------------------------------------
      *  Imported prototypes
      * ------------------------------------
      /COPY QJOBLOG,CLIB                          C Runtime Library
      /COPY QBASICS1,PBASICS1                     Tools/400 Runtime Library
      *
      * ------------------------------------
      *  Internal prototypes
      * ------------------------------------
      /COPY QJOBLOG,OPNLSTAPIS                    Process Open List APIs
      /COPY QJOBLOG,QGYOLJBL                      Open List of Job Log Messages (QGYOLJBL) API
      *
      *  Opens the job log and returns the first entry.
     D openJobLog...
     D                 PR              n
     D                                     extproc('openJobLog')
     D  i_qJob                             const likeds(qJob_t)
     D  i_options                          const like(JobLog_options_t)
     D  i_direction                        const like(JobLog_direction_t)
     D  i_msgKey                           const like(JobLog_msgKey_t)
     D  o_listInf                                likeds(qgy_opnListInf_t)
     D  o_options                                likeds(listOptions_t)
     D  o_errCode                                likeds(errCode_t)
      *
      *  Returns the next/previous job log entry.
     D getJobLogEntry...
     D                 PR                        likeds(JobLog_jobLogEntry_t)
     D                                     extproc('getJobLogEntry')
     D  i_hRequest                         const like(qgy_opnListInf_t.hRequest)
     D  i_rcdNbr                     10i 0 const
     D  i_options                          const likeds(listOptions_t)
     D  o_listInf                                likeds(qgy_opnListInf_t)
     D  o_errCode                                likeds(errCode_t)
      *
      *  Retrieves the character data of the specified field identifier.
     D getCharData...
     D                 PR          8192a          varying
     D                                     extproc('getCharData')
     D  i_buffer                  65535a          options(*varsize)
     D  i_buffLen                    10i 0 const
     D  i_fieldId                    10i 0 const
      *
      *  Retrieves the mixed data of the specified field identifier.
     D getMixedData...
     D                 PR                         likeds(mixedData_t)
     D                                     extproc('getMixedData')
     D  i_buffer                  65535a          options(*varsize)
     D  i_buffLen                    10i 0 const
     D  i_fieldId                    10i 0 const
      *
      *  Retrieves the binary data of the specified field identifier.
     D getBinData...
     D                 PR            10i 0
     D                                     extproc('getBinData')
     D  i_buffer                  65535a          options(*varsize)
     D  i_buffLen                    10i 0 const
     D  i_fieldId                    10i 0 const
      *
      *  Returns the data buffer of the specified field.
     D getData...
     D                 PR          8192a   varying
     D                                     extproc('getData')
     D  i_buffer                  65535a          options(*varsize)
     D  i_buffLen                    10i 0 const
     D  i_fieldId                    10i 0 const
      *
      *  Returns the default message key for a given direction.
     D getDftMsgKey...
     D                 PR                         like(JobLog_msgKey_t)
     D                                     extproc('getDftMsgKey')
     D  i_direction                        const  like(JobLog_direction_t)
      *
      *  Returns timestamp the message was send to the job log.
     D getTimeSent...
     D                 PR              Z
     D                                     extproc('getTimeSent')
     D  i_oljl0100                         const  likeds(oljl0100_t)
      *
      * ------------------------------------
      *  Global fields & constants
      * ------------------------------------
      *
      *=========================================================================
      *  Opens a job log.
      *=========================================================================
      *  Parameters:
      *   i_qJob        - Optional. Job whose job log is opened.
      *                   Default: current job
      *   i_options     - Optional. Specifies the information that is
      *                   retrieved from the job log.
      *                   Default: JOBLOG_PREVIOUS
      *   i_direction   - Optional. Direction to list the job log messages.
      *                   Default: JOBLOG_OPTION_MSG + JOBLOG_OPTION_REPLACE_VARS
      *   i_strMsgKey   - Optional. The message key to be used to begin
      *                   searching for messages to list from the job.
      *                   Default: depending on i_options.
      *
      *  Returns:
      *   hJobLog         Handle of the job log.
      *=========================================================================
     P JobLog_open...
     P                 B                   export
     D                 PI                         like(JobLog_handle_t)
     D  i_qJob                             const  likeds(qJob_t)
     D                                            options(*nopass: *omit)
     D  i_options                          const  like(JobLog_options_t)
     D                                            options(*nopass: *omit)
     D  i_direction                        const  like(JobLog_direction_t)
     D                                            options(*nopass: *omit)
     D  i_strMsgKey                        const  like(JobLog_msgKey_t)
     D                                            options(*nopass: *omit)
      *
      *  Return value
     D hJobLog         s                   like(JobLog_handle_t)
      *
      *  Parameter positions
     D p_qJob          c                   1
     D p_options       c                   2
     D p_direction     c                   3
     D p_strMsgKey     c                   4
      *
      *  Optional parameters
     D qJob            ds                  likeds(i_qJob) inz
     D options         s                   like(i_options) inz
     D direction       s                   like(i_direction) inz
     D strMsgKey       s                   like(i_strMsgKey) inz
      *
      *  Local fields
     D errCode         ds                  likeds(errCode_t) inz
      *
      *  Job log handle
     D handle          ds                  likeds(handle_t)
     D                                     based(pHandle)
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         if (%parms() >= p_qJob and %addr(i_qJob) <> *NULL);
            qJob = i_qJob;
         else;
            qJob.name = '*';
         endif;

         if (%parms() >= p_options and %addr(i_options) <> *NULL);
            options = i_options;
         else;
            options = JOBLOG_OPTION_MSG + JOBLOG_OPTION_REPLACE_VARS;
         endif;

         if (%parms() >= p_direction and %addr(i_direction) <> *NULL);
            direction = i_direction;
         else;
            direction = JOBLOG_PREVIOUS;
         endif;

         if (%parms() >= p_strMsgKey and %addr(i_strMsgKey) <> *NULL);
            strMsgKey = i_strMsgKey;
         else;
            strMsgKey = getDftMsgKey(direction);
         endif;

         hJobLog = HANDLE_new('*JOBLOG': %size(handle_t));
         pHandle = HANDLE_getPointer(hJobLog);

         clear handle;
         handle.isOpen = cFalse;
         handle.isEOF = cFalse;
         handle.qJob = qJob;
         handle.direction = direction;
         handle.strMsgKey = strMsgKey;
         handle.rcdNbr = 0;
         handle.listInf = *ALLx'00';

         handle.isOpen = openJobLog(
                            handle.qJob: options: handle.direction
                            : handle.strMsgKey: handle.listInf
                            : handle.options: errCode);

         return hJobLog;

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Closes a given job log.
      *=========================================================================
      *  Parameters:
      *   io_hJobLog    - Required. Handle that was returned by JobLog_open().
      *
      *  Returns:
      *   void
      *=========================================================================
     P JobLog_close...
     P                 B                   export
     D                 PI
     D  io_hJobLog                                like(JobLog_handle_t)
      *
      *  Local fields
     D errCode         ds                  likeds(errCode_t) inz
      *
      *  Job log handle
     D handle          ds                  likeds(handle_t)
     D                                     based(pHandle)
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         pHandle = HANDLE_getPointer(io_hJobLog);

         if (handle.isOpen);
            QGYCLST(handle.listInf.hRequest: errCode);
            handle.isOpen = cFalse;
         endif;

         HANDLE_delete(io_hJobLog);
         io_hJobLog = HANDLE_NULL;

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Returns the next job log entry.
      *=========================================================================
      *  Parameters:
      *   i_hJobLog     - Required. Handle that was returned by JobLog_open().
      *   o_jobLogEntry - Required.
      *
      *  Returns:
      *   hasData       - Returns cTrue if a job log entry is available,
      *                   else cFalse.
      *=========================================================================
     P JobLog_getEntry...
     P                 B                   export
     D                 PI              n
     D  i_hJobLog                          const  like(JobLog_handle_t)
     D  o_jobLogEntry                             likeds(JobLog_jobLogEntry_t)
      *
      *  Local fields
     D errCode         ds                  likeds(errCode_t) inz
      *
      *  Job log handle
     D handle          ds                  likeds(handle_t)
     D                                     based(pHandle)
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         pHandle = HANDLE_getPointer(i_hJobLog);

         if (handle.isEOF);
            return cFalse;
         endif;

         o_jobLogEntry = getJobLogEntry(handle.listInf.hRequest
                                        : handle.rcdNbr + 1
                                        : handle.options
                                        : handle.listInf
                                        : errCode);
         if (errCode.bytAvl <> 0);
            return cFalse;
         endif;

         handle.rcdNbr = handle.rcdNbr + 1;

         if (handle.rcdNbr >= handle.listInf.totalRcds);
            handle.isEOF = cTrue;
         endif;

         return cTrue;

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Returns the newest job log entry.
      *=========================================================================
      *  Parameters:
      *   i_qJob        - Optional. Full qualified name of the job whose
      *                   newest job log entry is returned.
      *   o_jobLogEntry - Required. Newest job log entry of the specified job.
      *
      *  Returns:
      *   isAvailable   - Returns cTrue on success, else cFalse.
      *=========================================================================
     P JobLog_getNewest...
     P                 B                   export
     D                 PI              n
     D  i_qJob                             const  likeds(qJob_t)
     D                                            options(*omit)
     D  o_jobLogEntry                             likeds(JobLog_jobLogEntry_t)
      *
      *  Return value
     D isAvailable     s               n   inz(cFalse)
      *
      *  Parameter positions
     D p_qJob          c                   1
      *
      *  Optional parameters
     D qJob            ds                  likeds(i_qJob) inz
      *
      *  Local fields
     D listInf         ds                  likeds(qgy_opnListInf_t) inz
     D options         ds                  likeds(listOptions_t) inz
     D errCode         ds                  likeds(errCode_t) inz
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         if (%parms() >= p_qJob and %addr(i_qJob) <> *NULL);
            qJob = i_qJob;
         else;
            qJob.name = '*';
         endif;

         isAvailable = cFalse;
         if (openJobLog(qJob
                        : JOBLOG_OPTION_MSG + JOBLOG_OPTION_REPLACE_VARS
                        : JOBLOG_PREVIOUS: getDftMsgKey(JOBLOG_PREVIOUS)
                        : listInf: options: errCode));
            o_jobLogEntry = getJobLogEntry(
                               listInf.hRequest: 1: options: listInf: errCode);
            if (listInf.RcdsRet > 0);
               isAvailable = cTrue;
            endif;
            QGYCLST(listInf.hRequest: errCode); // Close list
         endif;

         return isAvailable;

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Returns the oldest job log entry.
      *=========================================================================
      *  Parameters:
      *   i_qJob        - Optional. Full qualified name of the job whose
      *                   oldest job log entry is returned.
      *   o_jobLogEntry - Required. Oldest job log entry of the specified job.
      *
      *  Returns:
      *   isAvailable   - Returns cTrue on success, else cFalse.
      *=========================================================================
     P JobLog_getOldest...
     P                 B                   export
     D                 PI              n
     D  i_qJob                             const  likeds(qJob_t)
     D                                            options(*omit)
     D  o_jobLogEntry                             likeds(JobLog_jobLogEntry_t)
      *
      *  Return value
     D isAvailable     s               n   inz(cFalse)
      *
      *  Parameter positions
     D p_qJob          c                   1
      *
      *  Optional parameters
     D qJob            ds                  likeds(i_qJob) inz
      *
      *  Local fields
     D listInf         ds                  likeds(qgy_opnListInf_t) inz
     D options         ds                  likeds(listOptions_t) inz
     D errCode         ds                  likeds(errCode_t) inz
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         if (%parms() >= p_qJob and %addr(i_qJob) <> *NULL);
            qJob = i_qJob;
         else;
            qJob.name = '*';
         endif;

         isAvailable = cFalse;
         if (openJobLog(qJob
                        : JOBLOG_OPTION_MSG + JOBLOG_OPTION_REPLACE_VARS
                        : JOBLOG_NEXT: getDftMsgKey(JOBLOG_NEXT)
                        : listInf: options: errCode));
            o_jobLogEntry = getJobLogEntry(
                               listInf.hRequest: 1: options: listInf: errCode);
            if (listInf.RcdsRet > 0);
               isAvailable = cTrue;
            endif;
            QGYCLST(listInf.hRequest: errCode); // Close list
         endif;

         return isAvailable;

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Returns the message type of a given job log entry.
      *=========================================================================
      *  Parameters:
      *   job log entry - Job log entry returned by:
      *                      JobLog_getEntry()
      *                      JobLog_getNewest()
      *                      JobLog_getOldest()
      *
      *  Returns:
      *   msgType       - Message type
      *=========================================================================
     P JobLog_getMessageType...
     P                 B                   export
     D                 PI            10a
     D  i_jobLogEntry                      const  likeds(JobLog_jobLogEntry_t)
      *
     D msgType         s             10a   inz
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         select;
         when (i_jobLogEntry.msgType = '01');
            msgType = '*COMP';
         when (i_jobLogEntry.msgType = '02');
            msgType = '*DIAG';
         when (i_jobLogEntry.msgType = '04');
            msgType = '*INFO';
         when (i_jobLogEntry.msgType = '05');
            msgType = '*INQ';
         when (i_jobLogEntry.msgType = '06');
            msgType = '*COPY';
         when (i_jobLogEntry.msgType = '08');
            msgType = '*RQS';
         when (i_jobLogEntry.msgType = '10');
            msgType = '*RQS';
         when (i_jobLogEntry.msgType = '14');
            msgType = '*NOTIFY';
         when (i_jobLogEntry.msgType = '15');
            msgType = '*ESCAPE';
         when (i_jobLogEntry.msgType = '16');
            msgType = '*NOTIFY';
         when (i_jobLogEntry.msgType = '17');
            msgType = '*ESCAPE';
         when (i_jobLogEntry.msgType = '21');
            msgType = '*REPLY';
         when (i_jobLogEntry.msgType = '22');
            msgType = '*REPLY';
         when (i_jobLogEntry.msgType = '23');
            msgType = '*REPLY';
         when (i_jobLogEntry.msgType = '24');
            msgType = '*REPLY';
         when (i_jobLogEntry.msgType = '25');
            msgType = '*REPLY';
         when (i_jobLogEntry.msgType = '26');
            msgType = '*REPLY';
         other;
            msgType = '*N';
         endsl;

         return msgType;

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Returns cTrue if a given job log handle is NULL, else cFalse.
      *=========================================================================
      *  Parameters:
      *   i_hJobLog     - Required. Job log handle.
      *
      *  Returns:
      *   isNull        - Returns cTrue for a NULL handle, else cFalse.
      *=========================================================================
     P JobLog_isNull...
     P                 B                   export
     D                 PI              n
     D  i_hJobLog                                 like(JobLog_handle_t)
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         return Handle_isNull(i_hJobLog);

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Returns a NULL job log handle.
      *=========================================================================
      *  Parameters:
      *   void
      *
      *  Returns:
      *   handle        - A job log handle that is treated as NULL.
      *=========================================================================
     P JobLog_null...
     P                 B                   export
     D                 PI                         like(JobLog_handle_t)
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         return Handle_null();

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Opens the job log.
      *=========================================================================
     P openJobLog...
     P                 B
     D                 PI              n
     D  i_qJob                             const likeds(qJob_t)
     D  i_options                          const like(JobLog_options_t)
     D  i_direction                        const like(JobLog_direction_t)
     D  i_msgKey                           const like(JobLog_msgKey_t)
     D  o_listInf                                likeds(qgy_opnListInf_t)
     D  o_options                                likeds(listOptions_t)
     D  o_errCode                                likeds(errCode_t)
      *
      *  Return value
     D isOpen          s               n   inz(cFalse)
      *
      *  Local fields
     D buffSize        s             10i 0 inz
     D buffer          s          65535a   based(pBuffer)
     D offs            s             10i 0 inz
      *
     D slcInf          ds                  likeds(QGYOLJBL_msgSlcInf)
     D sizeSlcInf      s             10i 0 inz
      *
     D numFldsRtn      s             10i 0 inz
     D fldsToRtn       ds
     D  fldRtn                       10i 0 dim(32)
     D sizeFldsRtn     s             10i 0 inz
      *
     D callMsgQ        s              4a   inz
     D sizeCallMsgQ    s             10i 0 inz
      *
     D oljl0100_buffer...
     D                 s           8192
     D  oljl0100       ds                  likeds(oljl0100_t)
     D                                     based(pOljl0100)
     D pOljl0100       s               *   inz(%addr(oljl0100_buffer))
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         numFldsRtn = 0;
         clear o_options;

         // Return message text (first-level message text)
         if (f_isBitOn(JOBLOG_OPTION_MSG: i_options));
            o_options.isMsg = cTrue;
            numFldsRtn += 1;
            if (f_isBitOn(JOBLOG_OPTION_REPLACE_VARS: i_options));
               fldRtn(numFldsRtn) = QGYOLJBL_MSG_WITH_RPLC_DATA;
            else;
               fldRtn(numFldsRtn) = QGYOLJBL_MSG;
            endif;
            o_options.msgSelectId = fldRtn(numFldsRtn);
         endif;

         // Return message help (second-level message text)
         if (f_isBitOn(JOBLOG_OPTION_MSG_HELP: i_options));
            o_options.isMsgHelp = cTrue;
            numFldsRtn += 1;
            select;
            when (f_isBitOn(JOBLOG_OPTION_REPLACE_VARS: i_options) and
                  f_isBitOn(JOBLOG_OPTION_RETURN_CTRL_CHARS: i_options));
               fldRtn(numFldsRtn)=QGYOLJBL_MSG_HLP_WITH_RPLC_DATA_AND_FMT_CHARS;
            when (f_isBitOn(JOBLOG_OPTION_REPLACE_VARS: i_options));
               fldRtn(numFldsRtn)=QGYOLJBL_MSG_HLP_WITH_RPLC_DATA;
            when (f_isBitOn(JOBLOG_OPTION_RETURN_CTRL_CHARS: i_options));
               fldRtn(numFldsRtn)=QGYOLJBL_MSG_HLP_WITH_FMT_CHARS;
            other;
               fldRtn(numFldsRtn)=QGYOLJBL_MSG_HLP;
            endsl;
            o_options.hlpSelectId = fldRtn(numFldsRtn);
         endif;

         // Return replacement data
         numFldsRtn += 1;
         fldRtn(numFldsRtn) = QGYOLJBL_RPLC_DATA;

         // Return message file library used
         numFldsRtn += 1;
         fldRtn(numFldsRtn) = QGYOLJBL_MSGF_LIB;

         // Return sender information
         if (f_isBitOn(JOBLOG_OPTION_SENDER: i_options));
            o_options.isSender = cTrue;
            numFldsRtn += 1;
            fldRtn(numFldsRtn) = QGYOLJBL_QSND_JOB;   // Sending job
            numFldsRtn += 1;
            fldRtn(numFldsRtn) = QGYOLJBL_SND_TYPE;   // Sending type
            numFldsRtn += 1;
            fldRtn(numFldsRtn) = QGYOLJBL_SND_PGM;    // Sending program
            numFldsRtn += 1;
            fldRtn(numFldsRtn) = QGYOLJBL_SND_MODULE; // Sending module
            numFldsRtn += 1;
            fldRtn(numFldsRtn) = QGYOLJBL_SND_PROC;   // Sending procedure
            numFldsRtn += 1;
            fldRtn(numFldsRtn) = QGYOLJBL_SND_STMTS_ARRAY; // Send. stmts array
            numFldsRtn += 1;
            fldRtn(numFldsRtn) = QGYOLJBL_SND_USRPRF; // Sending suer profile
         else;
            o_options.isSender = cFalse;
         endif;

         // Return receiver information
         if (f_isBitOn(JOBLOG_OPTION_RECEIVER: i_options));
            o_options.isReceiver = cTrue;
            numFldsRtn += 1;
            fldRtn(numFldsRtn) = QGYOLJBL_RCV_TYPE;   // Receiving type
            numFldsRtn += 1;
            fldRtn(numFldsRtn) = QGYOLJBL_RCV_PGM;    // Receiving program
            numFldsRtn += 1;
            fldRtn(numFldsRtn) = QGYOLJBL_RCV_MODULE; // Receiving module
            numFldsRtn += 1;
            fldRtn(numFldsRtn) = QGYOLJBL_RCV_PROC;   // Receiving procedure
            numFldsRtn += 1;
            fldRtn(numFldsRtn) = QGYOLJBL_RCV_STMTS_ARRAY; // Recv. stmts array
         else;
            o_options.isReceiver = cFalse;
         endif;

         callMsgQ = '*';

         sizeSlcInf = %size(slcInf);
         sizeFldsRtn = numFldsRtn * 4;
         sizeCallMsgQ = %len(%trimR(callMsgQ));

         // Prepare selection information
         clear slcInf;
         slcInf.listDirection = i_direction;
         slcInf.qJob = i_qJob;
         slcInf.intJobID = '';
         slcInf.strMsgKey = i_msgKey;
         slcInf.maxMsgLen = JOBLOG_MAX_MSG_TEXT_LEN;
         slcInf.maxMsgHlpLen = 0;
         slcInf.ofsFldsIdnRtn = %size(slcInf);
         slcInf.numFldsRtn = numFldsRtn;
         slcInf.ofsCallMsgQNm = %size(slcInf) + sizeFldsRtn;
         slcInf.lenMsgQNm = 1;

         // Calculate buffer size of selection information
         buffSize = sizeSlcInf + sizeFldsRtn + sizeCallMsgQ;

         pBuffer = %alloc(%size(buffSize));
         offs = 0;
         memcpy(pBuffer + offs: %addr(slcInf): %size(slcInf));
         offs = offs + %size(slcInf);
         memcpy(pBuffer + offs: %addr(fldsToRtn): sizeFldsRtn);
         offs = offs + sizeFldsRtn;
         memcpy(pBuffer + offs: %addr(callMsgQ): sizeCallMsgQ);
         offs = offs + sizeCallMsgQ;

         QGYOLJBL(oljl0100_buffer: %size(oljl0100_buffer): o_listInf: 0
                  : %subst(buffer: 1: buffSize)
                  : buffSize
                  : o_errCode);

         if (o_errCode.bytAvl = 0);
            isOpen = cTrue;
         else;
            isOpen = cFalse;
         endif;

         if (pBuffer <> *NULL);
            dealloc(N) pBuffer;
         endif;

         return isOpen;

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Returns the next/previous job log entry.
      *=========================================================================
     P getJobLogEntry...
     P                 B
     D                 PI                        likeds(JobLog_jobLogEntry_t)
     D  i_hRequest                         const like(qgy_opnListInf_t.hRequest)
     D  i_rcdNbr                     10i 0 const
     D  i_options                          const likeds(listOptions_t)
     D  o_listInf                                likeds(qgy_opnListInf_t)
     D  o_errCode                                likeds(errCode_t)
      *
      *  Return value
     D jobLogEntry     ds                  likeds(JobLog_jobLogEntry_t) inz
      *
      *  Local fields
     D oljl0100_buffer...
     D                 s           8192
     D  oljl0100       ds                  likeds(oljl0100_t)
     D                                     based(pOljl0100)
     D pOljl0100       s               *   inz(%addr(oljl0100_buffer))
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         QGYGTLE(oljl0100_buffer: %size(oljl0100_buffer)
                 : i_hRequest: o_listInf: 1: i_rcdNbr: o_errCode);

         clear jobLogEntry;
         jobLogEntry.msgSeverity = oljl0100.msgSeverity;
         jobLogEntry.msgID = oljl0100.msgID;
         jobLogEntry.msgType = oljl0100.msgType;
         jobLogEntry.msgKey = oljl0100.msgKey;
         jobLogEntry.msgFile = oljl0100.msgFile;
         jobLogEntry.msgFLibSpcfd = oljl0100.msgFLibSpcfd;
         jobLogEntry.msgFLibUsed = getCharData(oljl0100_buffer
                                               : %size(oljl0100_buffer)
                                               : QGYOLJBL_MSGF_LIB);
         jobLogEntry.timeSent = getTimeSent(oljl0100);
         jobLogEntry.threadId = oljl0100.threadId;

         jobLogEntry.rplcData = getCharData(oljl0100_buffer
                                            : %size(oljl0100_buffer)
                                            : QGYOLJBL_RPLC_DATA);

         if (i_options.isMsg);
            jobLogEntry.msgText = getCharData(oljl0100_buffer
                                              : %size(oljl0100_buffer)
                                              : i_options.msgSelectId);
         endif;

         if (i_options.isMsgHelp);
            jobLogEntry.msgHelp = getCharData(oljl0100_buffer
                                              : %size(oljl0100_buffer)
                                              : i_options.hlpSelectId);
         endif;

         if (i_options.isSender);
            jobLogEntry.sender.job =
                  getCharData(oljl0100_buffer: %size(oljl0100_buffer)
                              : QGYOLJBL_QSND_JOB);
            jobLogEntry.sender.type =
                  getCharData(oljl0100_buffer: %size(oljl0100_buffer)
                              : QGYOLJBL_SND_TYPE);
            jobLogEntry.sender.pgm =
                  getCharData(oljl0100_buffer: %size(oljl0100_buffer)
                              : QGYOLJBL_SND_PGM);
            jobLogEntry.sender.mod =
                  getCharData(oljl0100_buffer: %size(oljl0100_buffer)
                              : QGYOLJBL_SND_MODULE);
            jobLogEntry.sender.proc =
                  getCharData(oljl0100_buffer: %size(oljl0100_buffer)
                              : QGYOLJBL_SND_PROC);
            jobLogEntry.sender.stmts =
                  getMixedData(oljl0100_buffer: %size(oljl0100_buffer)
                               : QGYOLJBL_SND_STMTS_ARRAY);
            jobLogEntry.sender.usrPrf =
                  getCharData(oljl0100_buffer: %size(oljl0100_buffer)
                              : QGYOLJBL_SND_USRPRF);
         endif;

         if (i_options.isReceiver);
            jobLogEntry.receiver.type =
                  getCharData(oljl0100_buffer: %size(oljl0100_buffer)
                              : QGYOLJBL_RCV_TYPE);
            jobLogEntry.receiver.pgm =
                  getCharData(oljl0100_buffer: %size(oljl0100_buffer)
                              : QGYOLJBL_RCV_PGM);
            jobLogEntry.receiver.mod =
                  getCharData(oljl0100_buffer: %size(oljl0100_buffer)
                              : QGYOLJBL_RCV_MODULE);
            jobLogEntry.receiver.proc =
                  getCharData(oljl0100_buffer: %size(oljl0100_buffer)
                              : QGYOLJBL_RCV_PROC);
            jobLogEntry.receiver.stmts =
                  getMixedData(oljl0100_buffer: %size(oljl0100_buffer)
                               : QGYOLJBL_RCV_STMTS_ARRAY);
         endif;

         return jobLogEntry;

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Retrieves the character data of the specified field identifier.
      *=========================================================================
     P getCharData...
     P                 B
     D                 PI          8192a          varying
     D  i_buffer                  65535a          options(*varsize)
     D  i_buffLen                    10i 0 const
     D  i_fieldId                    10i 0 const
      *
      *  Return value
     D fieldData       s           8192a   varying inz
      *
     D lenData         s             10i 0
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         p_assert(i_fieldId =  101 or i_fieldId =  201 or
                  i_fieldId =  301 or i_fieldId =  302 or
                  i_fieldId =  401 or i_fieldId =  402 or
                  i_fieldId =  403 or i_fieldId =  404 or
                  i_fieldId =  501 or i_fieldId =  601 or
                  i_fieldId =  602 or i_fieldId =  603 or
                  i_fieldId =  604 or i_fieldId =  605 or
                  i_fieldId =  607 or i_fieldId =  702 or
                  i_fieldId =  703 or i_fieldId =  704 or
                  i_fieldId =  705 or i_fieldId =  801 or
                  i_fieldId =  901 or i_fieldId = 1001 or
                  i_fieldId = 1101
         : 'Illegal procedure call for field with id: ' + %char(i_fieldId));

         fieldData = getData(i_buffer: i_buffLen: i_fieldId);

         return fieldData;

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Retrieves the mixed data of the specified field identifier.
      *=========================================================================
     P getMixedData...
     P                 B
     D                 PI                         likeds(mixedData_t)
     D  i_buffer                  65535a          options(*varsize)
     D  i_buffLen                    10i 0 const
     D  i_fieldId                    10i 0 const
      *
      *  Return value
     D fieldData       ds                  likeds(mixedData_t)
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         p_assert(i_fieldId = 606 or i_fieldId = 706
         : 'Illegal procedure call for field with id: ' + %char(i_fieldId));

         fieldData = getData(i_buffer: i_buffLen: i_fieldId);

         return fieldData;

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Retrieves the binary data of the specified field identifier.
      *=========================================================================
     P getBinData...
     P                 B
     D                 PI            10i 0
     D  i_buffer                  65535a          options(*varsize)
     D  i_buffLen                    10i 0 const
     D  i_fieldId                    10i 0 const
      *
      *  Return value
     D fieldData       s             10i 0 inz
      *
      *  Local fields
     D charBuffer      ds                  qualified
     D  toBinValue                   10i 0
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         p_assert(i_fieldId = 1201 or i_fieldId = 1301 or
                  i_fieldId = 1302 or i_fieldId = 1303 or
                  i_fieldId = 1304
         : 'Illegal procedure call for field with id: ' + %char(i_fieldId));

         charBuffer = getData(i_buffer: i_buffLen: i_fieldId);
         fieldData = charBuffer.toBinValue;

         return fieldData;

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Returns the data buffer of the specified field.
      *=========================================================================
     P getData...
     P                 B
     D                 PI          8192a   varying
     D  i_buffer                  65535a          options(*varsize)
     D  i_buffLen                    10i 0 const
     D  i_fieldId                    10i 0 const
      *
      *  Return value
     D fieldData       s           8192a   varying inz
      *
      *  Local fields
     D oljl0100        ds                  likeds(oljl0100_t)
     D                                     based(pOljl0100)
     D fieldInf        ds                  likeds(oljl0100_fieldInf_t)
     D                                     based(pFieldInf)
     D data            s           8192a   based(pData)
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         pOljl0100 = %addr(i_buffer);
         pFieldInf = pOljl0100 + oljl0100.ofsFldsRtn;

         dow (fieldInf.fieldId <> i_fieldId and fieldInf.ofsNxtFldInf <> 0);
            pFieldInf = pOljl0100 + fieldInf.ofsNxtFldInf;
         enddo;

         if (fieldInf.fieldId = i_fieldId);
            pData = pFieldInf + %size(fieldInf);
            fieldData = %subst(data: 1: fieldInf.lenData);
         else;
            fieldData = '';
         endif;

         return fieldData;

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Returns the default message key for a given direction.
      *=========================================================================
     P getDftMsgKey...
     P                 B
     D                 PI                         like(JobLog_msgKey_t)
     D  i_direction                        const  like(JobLog_direction_t)
      *
      *  Return value
     D msgKey          s                   like(JobLog_msgKey_t)
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

            if (i_direction = JOBLOG_PREVIOUS);
               msgKey = MSGKEY_PREVIOUS;
            else;
               msgKey = MSGKEY_NEXT;
            endif;

         return msgKey;

      /END-FREE
      *
     P                 E
      *
      *=========================================================================
      *  Returns timestamp the message was send to the job log.
      *=========================================================================
     P getTimeSent...
     P                 B
     D                 PI              Z
     D  i_oljl0100                         const  likeds(oljl0100_t)
      *
      *  Return value
     D timeSent        s               Z
      *
     D date            s               D
     D time            s               T
     D mSecs           s             10I 0
      * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      /FREE

         monitor;
            date = %date(i_oljl0100.dateSnd: *CYMD0);
            time = %time(i_oljl0100.timeSnd: *HMS0);
            mSecs = %int(i_oljl0100.mSecs);
            timeSent = date + time + %mseconds(mSecs);
         on-error;
            clear timeSent;
         endmon;

         return timeSent;

      /END-FREE
      *
     P                 E
      *
